#include "Adafruit_TinyUSB.h"
#include "esp_partition.h"
#include "esp_ota_ops.h"
const esp_partition_t* partition0 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
const esp_partition_t* partition1 = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, NULL);
const int PC_SWITCH = 3; // 替换为你连接的引脚号
const int PC_V = 37; // 替换为你连接的引脚号

#define RXD1 11
#define TXD1 12

#define POWER_EVT_START 247

#define KB_EVT_START 248
#define MOUSE_EVT_START 249
#define KEY_SEQUENCE_EVT_START 250
#define EVT_END 251
#define KB_EVT_TYPE_RESET 3
#define PARTITION_0 0
#define PARTITION_1 1
#define PC_POWER_ON 2
#define PC_POWER_OFF 3
#define PC_POWER_LONG 4
#define PC_POWER_S 5
#define PC_POWER_MODE 6

#define KB_EVT_TYPE_KEYDOWN 1
#define KB_EVT_TYPE_KEYUP 2
#define KB_EVT_TYPE_RESET 3

#define MOUSE_EVT_TYPE_MOVE 1
#define MOUSE_EVT_TYPE_LEFT_DOWN 2
#define MOUSE_EVT_TYPE_LEFT_UP 3
#define MOUSE_EVT_TYPE_MIDDLE_DOWN 4
#define MOUSE_EVT_TYPE_MIDDLE_UP 5
#define MOUSE_EVT_TYPE_RIGHT_DOWN 6
#define MOUSE_EVT_TYPE_RIGHT_UP 7
#define MOUSE_EVT_TYPE_WHEEL 8
#define MOUSE_EVT_TYPE_RESET 9
#define MOUSE_EVT_TYPE_CONFIG_MOVE_FACTOR 10
#define PC_POWER 11
#define PC_VOLTAGE 12
#define R_BUF_LEN 32
int pinVoltage = 0;
int rBuf[R_BUF_LEN];
int rBufCursor = 0;
int mouseMoveFactor = 1;
uint8_t buttons = 0;
uint8_t scan_code_map[256] = {0};
uint8_t count = 0;
uint8_t keycode[6] = {0};
uint8_t modifier = 0;
uint8_t const desc_hid_report[] = {
  TUD_HID_REPORT_DESC_KEYBOARD()
};

Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);




void setup()
{
    pinMode(PC_SWITCH, OUTPUT);
    digitalWrite(PC_SWITCH, LOW);
    pinMode(PC_V,INPUT);

    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);
    scan_code_map[97] = 0x04;
    scan_code_map[98] = 0x05;
    scan_code_map[99] = 0x06;
    scan_code_map[100] = 0x07;
    scan_code_map[101] = 0x08;
    scan_code_map[102] = 0x09;
    scan_code_map[103] = 0x0A;
    scan_code_map[104] = 0x0B;
    scan_code_map[105] = 0x0C;
    scan_code_map[106] = 0x0D;
    scan_code_map[107] = 0x0E;
    scan_code_map[108] = 0x0F;
    scan_code_map[109] = 0x10;
    scan_code_map[110] = 0x11;
    scan_code_map[111] = 0x12;
    scan_code_map[112] = 0x13;
    scan_code_map[113] = 0x14;
    scan_code_map[114] = 0x15;
    scan_code_map[115] = 0x16;
    scan_code_map[116] = 0x17;
    scan_code_map[117] = 0x18;
    scan_code_map[118] = 0x19;
    scan_code_map[119] = 0x1A;
    scan_code_map[120] = 0x1B;
    scan_code_map[121] = 0x1C;
    scan_code_map[122] = 0x1D;
    scan_code_map[49] = 0x1E;
    scan_code_map[50] = 0x1F;
    scan_code_map[51] = 0x20;
    scan_code_map[52] = 0x21;
    scan_code_map[53] = 0x22;
    scan_code_map[54] = 0x23;
    scan_code_map[55] = 0x24;
    scan_code_map[56] = 0x25;
    scan_code_map[57] = 0x26;
    scan_code_map[48] = 0x27;
    scan_code_map[176] = 0x28;
    scan_code_map[177] = 0x29;
    scan_code_map[178] = 0x2A;
    scan_code_map[179] = 0x2B;
    scan_code_map[32] = 0x2C;
    scan_code_map[45] = 0x2D;
    scan_code_map[61] = 0x2E;
    scan_code_map[91] = 0x2F;
    scan_code_map[93] = 0x30;
    scan_code_map[92] = 0x31;
    scan_code_map[59] = 0x33;
    scan_code_map[39] = 0x34;
    scan_code_map[96] = 0x35;
    scan_code_map[44] = 0x36;
    scan_code_map[46] = 0x37;
    scan_code_map[47] = 0x38;
    scan_code_map[193] = 0x39;
    scan_code_map[194] = 0x3A;
    scan_code_map[195] = 0x3B;
    scan_code_map[196] = 0x3C;
    scan_code_map[197] = 0x3D;
    scan_code_map[198] = 0x3E;
    scan_code_map[199] = 0x3F;
    scan_code_map[200] = 0x40;
    scan_code_map[201] = 0x41;
    scan_code_map[202] = 0x42;
    scan_code_map[203] = 0x43;
    scan_code_map[204] = 0x44;
    scan_code_map[205] = 0x45;
    scan_code_map[206] = 0x46;
    scan_code_map[207] = 0x47;
    scan_code_map[208] = 0x48;
    scan_code_map[209] = 0x49;
    scan_code_map[210] = 0x4A;
    scan_code_map[211] = 0x4B;
    scan_code_map[212] = 0x4C;
    scan_code_map[213] = 0x4D;
    scan_code_map[214] = 0x4E;
    scan_code_map[215] = 0x4F;
    scan_code_map[216] = 0x50;
    scan_code_map[217] = 0x51;
    scan_code_map[218] = 0x52;
    scan_code_map[42] = 0x55;
    scan_code_map[43] = 0x57;
    scan_code_map[13] = 0x58;
  Serial1.begin(115200, SERIAL_8N1, RXD1, TXD1);
  usb_hid.setReportCallback(NULL, NULL);
  usb_hid.begin();
  while (!TinyUSBDevice.mounted()) delay(1);
}
#define POWER_EVT_START 247

#define KB_EVT_START 248
#define MOUSE_EVT_START 249
#define KEY_SEQUENCE_EVT_START 250
#define EVT_END 251
void loop() {
  int curVal;
  while (Serial1.available() > 0) {
    curVal = Serial1.read();
    
    if (curVal == EVT_END) {
      parse_r_buf();
      // blink();
      reset_r_buf();
    } else {
      if (rBufCursor == 0) {
        if (curVal == POWER_EVT_START || KB_EVT_START || curVal == MOUSE_EVT_START || curVal == KEY_SEQUENCE_EVT_START) {
          rBuf[rBufCursor] = curVal;
          rBufCursor += 1;
        }
      } else {
        if (rBufCursor < R_BUF_LEN) {
           rBuf[rBufCursor] = curVal;
           rBufCursor += 1;
        } else {
          // overflow, reset rBuf
          rBuf[0] = 0;
        }
      }
    }
  }
}
uint8_t get_modifier_mask(uint8_t key) {
  switch (key) {
    case 128: return 0x01; // Left Ctrl
    case 129: return 0x02; // Left Shift
    case 130: return 0x04; // Left Alt
    case 131: return 0x08; // Left GUI (Windows/Command)
    default: return 0;
  }
}
void parse_r_buf() {
   if (rBuf[0] == KB_EVT_START && rBufCursor == 3) {
    uint8_t report_id = 0;
    uint8_t scan_code = scan_code_map[rBuf[2]];  // use mapping here
    switch (rBuf[1]) {
       case KB_EVT_TYPE_KEYDOWN:
        if (rBuf[2] > 127 && rBuf[2] < 132) {
          modifier |= get_modifier_mask(rBuf[2]);
        } else {
          keycode[count++] = scan_code;
        }
        break;
       case KB_EVT_TYPE_KEYUP:
        if (rBuf[2] > 127 && rBuf[2] < 132) {
          modifier &= ~get_modifier_mask(rBuf[2]);
        } else {
          release_key(scan_code);
        }
        break;
       case KB_EVT_TYPE_RESET:
        memset(keycode, 0, sizeof(keycode));
        count = 0;
        usb_hid.keyboardRelease(0);
        break;
    }
    usb_hid.keyboardReport(report_id, modifier, keycode);
  }




 if (rBuf[0] == POWER_EVT_START && rBufCursor == 2) {
    switch (rBuf[1]) {
      case PARTITION_0:
        esp_ota_set_boot_partition(partition0);
        esp_restart();
        break;
      case PARTITION_1:
        esp_ota_set_boot_partition(partition1);
        esp_restart();
        break;
      case PC_POWER_ON:
        // 发送高电平1.5秒到ESP32的pin13
        pinVoltage = digitalRead(PC_V);
        if (pinVoltage != HIGH) {
            digitalWrite(LED_BUILTIN, HIGH);

            digitalWrite(PC_SWITCH, HIGH);
            delay(1000);
            digitalWrite(PC_SWITCH, LOW);
            digitalWrite(LED_BUILTIN, LOW);


            } 
        break;
      case PC_POWER_OFF:
        // 发送高电平1.秒到ESP32的pin13
        pinVoltage = digitalRead(PC_V);
        if (pinVoltage == HIGH) {
            digitalWrite(LED_BUILTIN, HIGH);

            digitalWrite(PC_SWITCH, HIGH);
            delay(1000);
            digitalWrite(PC_SWITCH, LOW);
            digitalWrite(LED_BUILTIN, LOW);


            } 
        break;
                
      case PC_POWER_LONG:
        pinVoltage = digitalRead(PC_V);
        if (pinVoltage == HIGH) {
            // 发送高电平5秒到ESP32的pin13
            digitalWrite(LED_BUILTIN, HIGH);

            digitalWrite(PC_SWITCH, HIGH);
            delay(5000);
            digitalWrite(PC_SWITCH, LOW);
            digitalWrite(LED_BUILTIN, LOW);

            } 
        break;
      case PC_POWER_S:
        // 测量PC_V电压是高电平还是低电平
        pinVoltage = digitalRead(PC_V);
        // 判断PC_V的电压状态并在串口1上打印相应的消息
        if (pinVoltage == HIGH) {
          Serial1.println("poweron");
        } else if (pinVoltage == LOW) {
          Serial1.println("poweroff");
        }
        break;
      case PC_POWER_MODE:
        Serial1.println("mode1");
        break;
    }
  }
}

void release_key(uint8_t key)
{
  for (uint8_t i = 0; i < count; i++)
  {
    if (keycode[i] == key)
    {
      for (uint8_t j = i; j < count - 1; j++)
      {
        keycode[j] = keycode[j + 1];
      }

      count--;
      keycode[count] = 0;
      break;
    }
  }
}
void reset_r_buf() {
   rBufCursor = 0;
   rBuf[0] = 0;
}

